/*
 * Tencent is pleased to support the open source community by making TBase available.  
 * 
 * Copyright (C) 2019 Tencent.  All rights reserved.
 * 
 * TBase is licensed under the BSD 3-Clause License, except for the third-party component listed below. 
 * 
 * A copy of the BSD 3-Clause License is included in this file.
 * 
 * Other dependencies and licenses:
 * 
 * Open Source Software Licensed Under the PostgreSQL License: 
 * --------------------------------------------------------------------
 * 1. Postgres-XL XL9_5_STABLE
 * Portions Copyright (c) 2015-2016, 2ndQuadrant Ltd
 * Portions Copyright (c) 2012-2015, TransLattice, Inc.
 * Portions Copyright (c) 2010-2017, Postgres-XC Development Group
 * Portions Copyright (c) 1996-2015, The PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, The Regents of the University of California
 * 
 * Terms of the PostgreSQL License: 
 * --------------------------------------------------------------------
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose, without fee, and without a written agreement
 * is hereby granted, provided that the above copyright notice and this
 * paragraph and the following two paragraphs appear in all copies.
 * 
 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING
 * LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
 * DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 * 
 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
 * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 * 
 * 
 * Terms of the BSD 3-Clause License:
 * --------------------------------------------------------------------
 * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
 * 
 * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
 * 
 * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation 
 * and/or other materials provided with the distribution.
 * 
 * 3. Neither the name of Tencent nor the names of its contributors may be used to endorse or promote products derived from this software without 
 * specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 
 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 
 * DAMAGE.
 * 
 */
/*
 * px.h
 *        Header file for pgcrypto.
 *
 * Copyright (c) 2001 Marko Kreen
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * contrib/pgcrypto/px.h
 */

#ifndef __PX_H
#define __PX_H

#include <sys/types.h>
#include <sys/param.h>

/* keep debug messages? */
#define PX_DEBUG

/* max len of 'type' parms */
#define PX_MAX_NAMELEN        128

/* max salt returned */
#define PX_MAX_SALT_LEN        128

/*
 * PX error codes
 */
#define PXE_OK                        0
#define PXE_ERR_GENERIC                -1
#define PXE_NO_HASH                    -2
#define PXE_NO_CIPHER                -3
#define PXE_NOTBLOCKSIZE            -4
#define PXE_BAD_OPTION                -5
#define PXE_BAD_FORMAT                -6
#define PXE_KEY_TOO_BIG                -7
#define PXE_CIPHER_INIT                -8
#define PXE_HASH_UNUSABLE_FOR_HMAC    -9
#define PXE_DEV_READ_ERROR            -10
#define PXE_OSSL_RAND_ERROR            -11
#define PXE_BUG                        -12
#define PXE_ARGUMENT_ERROR            -13
#define PXE_UNKNOWN_SALT_ALGO        -14
#define PXE_BAD_SALT_ROUNDS            -15
#define PXE_MCRYPT_INTERNAL            -16
#define PXE_NO_RANDOM                -17
#define PXE_DECRYPT_FAILED            -18

#define PXE_PGP_CORRUPT_DATA        -100
#define PXE_PGP_CORRUPT_ARMOR        -101
#define PXE_PGP_UNSUPPORTED_COMPR    -102
#define PXE_PGP_UNSUPPORTED_CIPHER    -103
#define PXE_PGP_UNSUPPORTED_HASH    -104
#define PXE_PGP_COMPRESSION_ERROR    -105
#define PXE_PGP_NOT_TEXT            -106
#define PXE_PGP_UNEXPECTED_PKT        -107
#define PXE_PGP_NO_BIGNUM            -108
#define PXE_PGP_MATH_FAILED            -109
#define PXE_PGP_SHORT_ELGAMAL_KEY    -110
#define PXE_PGP_RSA_UNSUPPORTED        -111
#define PXE_PGP_UNKNOWN_PUBALGO        -112
#define PXE_PGP_WRONG_KEY            -113
#define PXE_PGP_MULTIPLE_KEYS        -114
#define PXE_PGP_EXPECT_PUBLIC_KEY    -115
#define PXE_PGP_EXPECT_SECRET_KEY    -116
#define PXE_PGP_NOT_V4_KEYPKT        -117
#define PXE_PGP_KEYPKT_CORRUPT        -118
#define PXE_PGP_NO_USABLE_KEY        -119
#define PXE_PGP_NEED_SECRET_PSW        -120
#define PXE_PGP_BAD_S2K_MODE        -121
#define PXE_PGP_UNSUPPORTED_PUBALGO -122
#define PXE_PGP_MULTIPLE_SUBKEYS    -123


typedef struct px_digest PX_MD;
typedef struct px_alias PX_Alias;
typedef struct px_hmac PX_HMAC;
typedef struct px_cipher PX_Cipher;
typedef struct px_combo PX_Combo;

struct px_digest
{
    unsigned    (*result_size) (PX_MD *h);
    unsigned    (*block_size) (PX_MD *h);
    void        (*reset) (PX_MD *h);
    void        (*update) (PX_MD *h, const uint8 *data, unsigned dlen);
    void        (*finish) (PX_MD *h, uint8 *dst);
    void        (*free) (PX_MD *h);
    /* private */
    union
    {
        unsigned    code;
        void       *ptr;
    }            p;
};

struct px_alias
{
    char       *alias;
    char       *name;
};

struct px_hmac
{
    unsigned    (*result_size) (PX_HMAC *h);
    unsigned    (*block_size) (PX_HMAC *h);
    void        (*reset) (PX_HMAC *h);
    void        (*update) (PX_HMAC *h, const uint8 *data, unsigned dlen);
    void        (*finish) (PX_HMAC *h, uint8 *dst);
    void        (*free) (PX_HMAC *h);
    void        (*init) (PX_HMAC *h, const uint8 *key, unsigned klen);

    PX_MD       *md;
    /* private */
    struct
    {
        uint8       *ipad;
        uint8       *opad;
    }            p;
};

struct px_cipher
{
    unsigned    (*block_size) (PX_Cipher *c);
    unsigned    (*key_size) (PX_Cipher *c);        /* max key len */
    unsigned    (*iv_size) (PX_Cipher *c);

    int            (*init) (PX_Cipher *c, const uint8 *key, unsigned klen, const uint8 *iv);
    int            (*encrypt) (PX_Cipher *c, const uint8 *data, unsigned dlen, uint8 *res);
    int            (*decrypt) (PX_Cipher *c, const uint8 *data, unsigned dlen, uint8 *res);
    void        (*free) (PX_Cipher *c);
    /* private */
    void       *ptr;
    int            pstat;            /* mcrypt uses it */
};

struct px_combo
{
    int            (*init) (PX_Combo *cx, const uint8 *key, unsigned klen,
                                     const uint8 *iv, unsigned ivlen);
    int            (*encrypt) (PX_Combo *cx, const uint8 *data, unsigned dlen,
                                        uint8 *res, unsigned *rlen);
    int            (*decrypt) (PX_Combo *cx, const uint8 *data, unsigned dlen,
                                        uint8 *res, unsigned *rlen);
    unsigned    (*encrypt_len) (PX_Combo *cx, unsigned dlen);
    unsigned    (*decrypt_len) (PX_Combo *cx, unsigned dlen);
    void        (*free) (PX_Combo *cx);

    PX_Cipher  *cipher;
    unsigned    padding;
};

int            px_find_digest(const char *name, PX_MD **res);
int            px_find_hmac(const char *name, PX_HMAC **res);
int            px_find_cipher(const char *name, PX_Cipher **res);
int            px_find_combo(const char *name, PX_Combo **res);

int            px_get_random_bytes(uint8 *dst, unsigned count);
int            px_add_entropy(const uint8 *data, unsigned count);

unsigned    px_acquire_system_randomness(uint8 *dst);

const char *px_strerror(int err);

const char *px_resolve_alias(const PX_Alias *aliases, const char *name);

void        px_set_debug_handler(void (*handler) (const char *));



#ifdef PX_DEBUG
void
px_debug(const char *fmt,...)
__attribute__((format(PG_PRINTF_ATTRIBUTE, 1, 2)));
#else
#define px_debug(...)
#endif

#define px_md_result_size(md)        (md)->result_size(md)
#define px_md_block_size(md)        (md)->block_size(md)
#define px_md_reset(md)            (md)->reset(md)
#define px_md_update(md, data, dlen)    (md)->update(md, data, dlen)
#define px_md_finish(md, buf)        (md)->finish(md, buf)
#define px_md_free(md)            (md)->free(md)

#define px_hmac_result_size(hmac)    (hmac)->result_size(hmac)
#define px_hmac_block_size(hmac)    (hmac)->block_size(hmac)
#define px_hmac_reset(hmac)        (hmac)->reset(hmac)
#define px_hmac_init(hmac, key, klen)    (hmac)->init(hmac, key, klen)
#define px_hmac_update(hmac, data, dlen) (hmac)->update(hmac, data, dlen)
#define px_hmac_finish(hmac, buf)    (hmac)->finish(hmac, buf)
#define px_hmac_free(hmac)        (hmac)->free(hmac)


#define px_cipher_key_size(c)        (c)->key_size(c)
#define px_cipher_block_size(c)        (c)->block_size(c)
#define px_cipher_iv_size(c)        (c)->iv_size(c)
#define px_cipher_init(c, k, klen, iv)    (c)->init(c, k, klen, iv)
#define px_cipher_encrypt(c, data, dlen, res) \
                    (c)->encrypt(c, data, dlen, res)
#define px_cipher_decrypt(c, data, dlen, res) \
                    (c)->decrypt(c, data, dlen, res)
#define px_cipher_free(c)        (c)->free(c)


#define px_combo_encrypt_len(c, dlen)    (c)->encrypt_len(c, dlen)
#define px_combo_decrypt_len(c, dlen)    (c)->decrypt_len(c, dlen)
#define px_combo_init(c, key, klen, iv, ivlen) \
                    (c)->init(c, key, klen, iv, ivlen)
#define px_combo_encrypt(c, data, dlen, res, rlen) \
                    (c)->encrypt(c, data, dlen, res, rlen)
#define px_combo_decrypt(c, data, dlen, res, rlen) \
                    (c)->decrypt(c, data, dlen, res, rlen)
#define px_combo_free(c)        (c)->free(c)


extern void crypt_free(void * ptr);
extern void * crypt_alloc(int size);
extern void * crypt_realloc(void * ptr, int size);
extern void *crypt_memset(void *s, int c, size_t n);
#endif   /* __PX_H */
